home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
telecomm
/
sticpsrc.lzh
/
SOURCE.ARC
/
AX25SERV.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-10-06
|
27KB
|
1,041 lines
/* AX25 server code */
#include <stdio.h>
#include <ctype.h>
#include "global.h"
#include "config.h"
#include "mbuf.h"
#include "iface.h"
#include "timer.h"
#include "ax25.h"
#include "lapb.h"
#include "cmdparse.h"
#include "session.h"
#include "slip.h"
#include "tnc2.h"
#ifdef AX25
/* "start" and "stop" subcommands */
static int tnc_start(),axdigi_start(),mheard_start(),bridge_start(),
tnc2_start(),mbox_start();
static struct cmds axstartcmds[] = {
"bridge", bridge_start, 0, NULLCHAR, "cannot start bridge",
#ifdef SMTPC
"mbox", mbox_start, 0, NULLCHAR, "cannot start mbox",
#endif
#ifdef MHEARD
"mheard", mheard_start, 0, NULLCHAR, "cannot start mheard",
#endif
"netdigi", axdigi_start, 0, NULLCHAR, "cannot start netdigi",
"tnc", tnc_start, 0, NULLCHAR, "cannot start tnc",
#ifdef TNC2
"tnc2", tnc2_start, 2, "[<dev>=]<iface> ...",
"cannot start tnc2",
#endif
NULLCHAR, NULLFP, 0,
"?options", NULLCHAR
};
static int tnc_stop(),axdigi_stop(),mheard_stop(),bridge_stop(),
tnc2_stop(),mbox_stop();
static struct cmds axstopcmds[] = {
"bridge", bridge_stop, 0, NULLCHAR, NULLCHAR,
#ifdef SMTPC
"mbox", mbox_stop, 0, NULLCHAR, NULLCHAR,
#endif
#ifdef MHEARD
"mheard", mheard_stop, 0, NULLCHAR, NULLCHAR,
#endif
"netdigi", axdigi_stop, 0, NULLCHAR, NULLCHAR,
"tnc", tnc_stop, 0, NULLCHAR, NULLCHAR,
#ifdef TNC2
"tnc2", tnc2_stop, 0, NULLCHAR, "cannot stop tnc2",
#endif
NULLCHAR, NULLFP, 0,
"?options", NULLCHAR
};
static void digi_a_state(),digi_b_state(),digi_recv(),digi_send();
static void mheard_state(),mheard_send();
static void bridge_recv(),bridge_state();
void close_ax25(),disc_ax25();
extern char nospace[];
extern char *ax25mesgs[];
/* start and stop command multiplexers */
doaxstart(argc,argv)
int argc;
char *argv[];
{
return subcmd(axstartcmds,argc,argv);
}
doaxstop(argc,argv)
int argc;
char *argv[];
{
return subcmd(axstopcmds,argc,argv);
}
/* start an ax25 server */
static
ax_sstart (port,r_upcall,t_upcall,s_upcall)
int port;
void (*r_upcall)(),(*t_upcall)(),(*s_upcall)();
{
register struct ax25_call *axp;
int found = 0;
void ax_noserv();
for(axp = ax25_port; axp != NULLAXCALL; axp = axp->p_next){
if(axp->port == port && axp->s_upcall == ax_noserv){
axp->r_upcall = r_upcall;
axp->t_upcall = t_upcall;
axp->s_upcall = s_upcall;
found++;
}
}
if(!found){
printf("port number %d not found or busy\n",port);
return 1;
}
return 0;
}
/* stop an ax25 server */
static
ax_sstop (port)
int port;
{
register struct ax25_call *axp;
void ax_noserv();
for (axp = ax25_port; axp != NULLAXCALL; axp = axp->p_next){
if(axp->port == port){
axp->r_upcall = axp->t_upcall = NULLVFP;
axp->s_upcall = ax_noserv;
}
}
}
char *tnc_conn_msg = NULLCHAR; /* connect message for TNC */
/* Start up tnc server */
static
tnc_start(argc,argv)
int argc;
char *argv[];
{
void tnc_state();
char mesg[256];
int i;
if(argc > 1){ /* set-up a connect message */
mesg[0] = '\0';
for(i = 1; i < argc; i++){
strcat(mesg,argv[i]);
strcat(mesg,"\r");
}
if(tnc_conn_msg != NULLCHAR)
free(tnc_conn_msg);
if((tnc_conn_msg = malloc(strlen(mesg)+2)) != NULLCHAR){
tnc_conn_msg[0] = PID_FIRST|PID_LAST|PID_NO_L3;
strcpy(tnc_conn_msg + 1,mesg);
}
}
return ax_sstart(TNCPORT,NULLVFP,NULLVFP,tnc_state);
}
/* Shut down tnc server */
static
tnc_stop()
{
return ax_sstop(TNCPORT);
}
/* Handle new incoming terminal sessions
* This is the default state-change upcall function, used when
* someone else connects to us
*/
void
tnc_state(axp,old,new,msg)
register struct ax25_cb *axp;
int old,new,msg;
{
struct session *s;
char remote[100];
long tloc;
void ax_rx(),ax_tx(),ax_state();
int ax_parse();
if(new != CONNECTED || msg != LAPBCONN) /* only interested in new connections */
return;
if((s = newsession()) == NULLSESSION){
/* Out of sessions, send DM */
axp->state = DISCONNECTED;
return;
}
pax25(remote,&axp->addr.dest);
if ((s->name = malloc((int16)strlen(remote)+1)) == NULLCHAR){
freesession(s);
axp->state = DISCONNECTED;
return;
}
s->type = AX25TNC;
s->cb.ax25_cb = axp;
s->parse = ax_parse;
strcpy(s->name,remote);
stop_timer(&axp->t4); /* no T4 disconnects on TNC links */
axp->t4.start = 0;
axp->r_upcall = ax_rx;
axp->t_upcall = ax_tx;
axp->s_upcall = ax_state;
axp->user = (char *)s;
pdax25(remote,&axp->addr); /* add digipeaters */
time(&tloc);
printf("\007%.15s Incoming AX25 session %lu from %s(%s)\n",
ctime(&tloc) + 4,(long) (s - sessions),remote,axp->interface->name);
fflush(stdout);
log_ax(axp,"Incoming AX25 session");
if(tnc_conn_msg != NULLCHAR) /* a connect message defined? */
enqueue(&axp->txq,qstring(tnc_conn_msg));
}
/* Start up netdigi server */
static
axdigi_start(argc,argv)
int argc;
char *argv[];
{
return ax_sstart(NETDIGIPORT,NULLVFP,NULLVFP,digi_a_state);
}
/* Shut down netdigi server */
static
axdigi_stop()
{
return ax_sstop(NETDIGIPORT);
}
static void
digi_a_state(axp,old,new,msg)
register struct ax25_cb *axp;
int old,new,msg;
{
register struct ax25_cb *axpb;
register int i,j;
struct ax25_cb *find_ax25(),*cr_ax25();
struct ax25_call *axport;
struct ax25_addr usecall;
struct ax25 addr;
char mesg[128],tmp[10];
extern int16 t1init,t2init;
axpb = find_ax25(&axp->addr.source,&axp->addr.dest);
switch (new)
{
case CONNECTED:
if(old != DISCONNECTED || msg != LAPBCONN)/* not a new connection? */
return; /* ignore state change */
if(axpb != NULLAX25) { /* connection already exists */
axp->state = DISCONNECTED;
return;
}
/* New connection via NetDigi, setup response and 2nd link */
pax25(tmp,&((struct ax25_call *) axp->user)->addr);
sprintf(mesg,"%cNetDigi %s: Please wait for connection.\r",
PID_FIRST|PID_LAST|PID_NO_L3,tmp);
/* must not call send_ax25 because it would send out the
message even before the UA was transmitted */
enqueue(&axp->txq,qstring(mesg));
ASSIGN(usecall,((struct ax25_call *) axp->user)->addr);
for (axport = ax25_port; axport != NULLAXCALL; axport = axport->p_next){
if(axport->port == NETDIGIPORT &&
axport->interface == axp->interface){
ASSIGN(usecall,axport->addr);
}
}
usecall.ssid &= ~E;
/* Swap source and destination, reverse digi string */
ASSIGN(addr.source,axp->addr.dest);
ASSIGN(addr.dest,axp->addr.source);
/* Construct reverse digipeater path */
for(i=axp->addr.ndigis-1,j=0;i >= 0;i--,j++){
ASSIGN(addr.digis[j],axp->addr.digis[i]);
addr.digis[j].ssid &= ~(E|REPEATED);
}
addr.ndigis = axp->addr.ndigis;
/* set all repeated flags up to my callsign */
for(i=axp->addr.ndigis-1;i >= 0; i--){
if(addreq(&addr.digis[i],&((struct ax25_call *) axp->user)->addr)){
/* found my call, replace it by port call for input iface */
ASSIGN(addr.digis[i],usecall);
j = i; /* for timer values calc */
while (i >= 0)
addr.digis[i--].ssid |= REPEATED;
}
}
/* create controlblock, but do not yet open connection */
if((axpb = cr_ax25(&addr.dest,&addr.source)) != NULLAX25){
ASSIGN(axpb->addr,addr);
/* compute timer values depending on real digipeaters */
axpb->t1.start = t1init * (addr.ndigis - j);
axpb->t2.start = t2init * (addr.ndigis - j);
axpb->window = axp->window = axp->maxframe * axp->paclen;
axpb->r_upcall = axp->r_upcall = digi_recv;
axpb->t_upcall = axp->t_upcall = digi_send;
axpb->s_upcall = digi_b_state;
if(((struct ax25_call *) axp->user)->interface != NULLIF)
axpb->interface = ((struct ax25_call *) axp->user)->interface;
else
axpb->interface = axp->interface;
lapbstate(axpb,SETUP,LAPBNOMS); /* leave it in SETUP state */
if(axp->interface == axpb->interface) /* both on same band? */
axp->t2.start = axpb->t2.start = 0; /* disable T2 for